package com.boot2.core.utils;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.net.URL;
import java.security.MessageDigest;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串操作工具
 *
 * @author malongbo
 */
public final class StringUtils extends org.apache.commons.lang3.StringUtils {

    final static Pattern mobilePattern = Pattern.compile("^1\\d{10}$");
    final static Pattern userNamePt = Pattern.compile("^lv[0-9]{11}$");
    final static Pattern pinyinPattern = Pattern.compile("([a-z|A-Z]*)");
    final static Pattern datePattern = Pattern.compile(
            "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
    private static final Log log = LogFactory.getLog(StringUtils.class);
    // 转成小写
    public static final int toLowerCase = 1;

    // 转成大写
    public static final int toUpperCase = 2;

    private static final String MOBILE_REG = "^(13[0-9]|14[0-9]|15[0-9]|18[0-9]|17[0-9])\\d{8}$";
    private static final String EMAIL_REG = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";

    /**
     * 判断字符串是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        if (str == null) {
            return true;
        }

        if ("".equals(str.trim())) {
            return true;
        }

        return false;
    }

    /**
     * 判断字符串是否不为空
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

//    /**
//     * 判断字符串是否为空字符串
//     *
//     * @param str
//     * @return
//     */
//    public static boolean isBlank(String str) {
//        return "".equals(str.trim());
//    }
//
//    /**
//     * 判断字符串是否为非空字符串
//     *
//     * @param str
//     * @return
//     */
//    public static boolean isNotBlank(String str) {
//        return !isBlank(str);
//    }

    /**
     * 将字符串转为boolean类型
     *
     * @param value
     * @param defaultValue 设置默认值，默认使用false
     * @return
     */
    public static Boolean toBoolean(String value, boolean defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }

        try {
            return Boolean.parseBoolean(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 将字符串转为boolean类型
     *
     * @param value
     * @return
     */
    public static Boolean toBoolean(String value) {
        return toBoolean(value, false);
    }

    /**
     * 将字符串转为long类型
     *
     * @param value
     * @param defaultValue 设置默认值
     * @return
     */
    public static Long toLong(String value, Long defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }
        try {
            return Long.parseLong(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 将字符串转为int类型
     *
     * @param value
     * @param defaultValue 设置默认值
     * @return
     */
    public static Integer toInt(String value, Integer defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 将字符串转为double类型
     *
     * @param value
     * @param defaultValue
     * @return
     */
    public static Double toDouble(String value, Double defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }
        try {
            return Double.parseDouble(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 将字符串转为float类型
     *
     * @param value
     * @param defaultValue
     * @return
     */
    public static Float toFloat(String value, Float defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }
        try {
            return Float.parseFloat(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 将数组值按英文逗号拼接成字符串
     *
     * @param array
     * @return
     */
    public static String join(Object[] array) {
        return join(array, ",", "");
    }

    /**
     * 将数组值按指定分隔符拼接成字符串
     *
     * @param array
     * @param delimiter 分割符，默认使用英文逗号
     * @return
     */
    public static String join(Object[] array, String delimiter) {

        return join(array, delimiter, "");
    }


    /**
     * 将数组值按指定分隔符拼接成字符串 <br>
     * </br>
     * <b>示例</b>： <br>
     * </br>
     * array等于new String[]{"a","b"} <br>
     * </br>
     * delimiter等于, <br>
     * </br>
     * surround等于' <br>
     * </br>
     * 转换结果为：'a','b'
     *
     * @param array
     * @param delimiter 分割符，默认使用英文逗号
     * @param surround  每个值左右符号，默认无
     * @return
     */
    public static String join(Object[] array, String delimiter, String surround) {
        if (array == null) {
            throw new IllegalArgumentException("Array can not be null");
        }

        if (array.length == 0) {
            return "";
        }

        if (surround == null) {
            surround = "";
        }

        if (delimiter == null) {
            surround = ",";
        }

        StringBuffer buffer = new StringBuffer();

        for (Object item : array) {
            buffer.append(surround).append(item.toString()).append(surround).append(delimiter);
        }

        buffer.delete(buffer.length() - delimiter.length(), buffer.length());

        return buffer.toString();
    }

    /**
     * Encode a string using algorithm specified in web.xml and return the resulting
     * encrypted password. If exception, the plain credentials string is returned
     *
     * @param password  Password or other credentials to use in authenticating this
     *                  username
     * @param algorithm Algorithm used to do the digest
     * @return encypted password based on the algorithm.
     */
    public static String encodePassword(String password, String algorithm) {
        byte[] unencodedPassword = password.getBytes();

        MessageDigest md = null;

        try {
            // first create an instance, given the provider
            md = MessageDigest.getInstance(algorithm);
        } catch (Exception e) {
            return password;
        }

        md.reset();

        // call the update method one or more times
        // (useful when you don't know the size of your data, eg. stream)
        md.update(unencodedPassword);

        // now calculate the hash
        byte[] encodedPassword = md.digest();

        StringBuffer buf = new StringBuffer();

        for (int i = 0; i < encodedPassword.length; i++) {
            if ((encodedPassword[i] & 0xff) < 0x10) {
                buf.append("0");
            }

            buf.append(Long.toString(encodedPassword[i] & 0xff, 16));
        }

        return buf.toString();
    }

    /**
     * 生成随机字符串
     *
     * @param random
     * @param len
     * @return
     */
    public static String getRandomString(int len) {
        Random rd = new Random();
        StringBuffer sb = new StringBuffer();
        int rdGet; // 取得随机数
        char ch;

        for (int i = 0; i < len; i++) {
            rdGet = Math.abs(rd.nextInt()) % 10 + 48; // 产生48到57的随机数(0-9的键位值)
            // rdGet=Math.abs(rd.nextInt())%26+97; // 产生97到122的随机数(a-z的键位值)
            ch = (char) rdGet;
            sb.append(ch);
        }
        return sb.toString();
    }

    /**
     * 该值去掉了字符O
     */
    private static final String RANDOM_STRING_POOL = "ABCDEFGHIJKLMNPQRSTUVWXYZ";

    public static String subStringStr(String str, int size) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        if (str.length() < size) {
            return str;
        }

        String lastString = str.substring(0, size) + "...";
        return lastString;
    }

    public static String subStringBr(String str) {
        String regex = "\\u002B";
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        String strBr = str.replaceAll(regex, "<br/>");
        return strBr;
    }

    public static String leftPadAndSubString(final String str, final int size, String padStr) {
        String str2 = leftPad(str, size, padStr);
        str2 = substring(str2, 0, size);
        return str2;
    }

    public static String subStringStrNoSuffix(String str, int size) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        if (str.length() < size) {
            return str;
        }

        String lastString = str.substring(0, size);
        return lastString;
    }

    /**
     * 判断传入的字符串是否为空串
     *
     * @return
     */
    public static boolean isEmptyString(String str) {
        return str == null ? true : str.trim().equals("") ? true : false;
    }

    /**
     * 我喜欢这样用。
     *
     * @return
     */
    public static boolean isNotEmptyString(String str) {
        return !isEmptyString(str);
    }

    // public static String getVstVisaCnName(String code){
    // if(isEmptyString(code)){
    // return "";
    // }
    // return Constant.OCCUP_TYPE.getCnName(code);
    // }

    /**
     * 替换模板中的变量。变量的标识符为${}。 例如，模板中${name}变量将会被Map列表中键名为name的键值替换，如果Map列表中不存在所需要
     * 的键名，则会被替换成空。
     *
     * @param template 模板
     * @param data     参数列表
     * @return
     * @throws Exception
     * @author Brian
     */
    public static String composeMessage(String template, Map<String, Object> data) {
        String regex = "\\$\\{(.+?)\\}";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(template);

        /*
         * sb用来存储替换过的内容，它会把多次处理过的字符串按源字符串序 存储起来。
         */
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String name = matcher.group(1);// 键名
            String value = null == data.get(name) ? "" : data.get(name).toString();// 键值
            if (value == null) {
                value = "";
            } else {
                value = value.replaceAll("\\$", "\\\\\\$");
                // value = value.replaceAll("\\", "\\\\");
            }

            matcher.appendReplacement(sb, value);
        }

        matcher.appendTail(sb);
        return sb.toString();
    }

    public static String getPercent(int n, Float f) {
        java.text.NumberFormat nf = java.text.NumberFormat.getPercentInstance();
        nf.setMinimumFractionDigits(n);// 小数点后保留几位
        String str = nf.format(f);// 要转化的数
        return str;
    }

    /**
     * 判断传入的字符串是否为空串,如果是null的就替换为""空字符串.
     *
     * @return
     */
    public static String replaceNullStr(String str) {
        if (str == null) {
            return "";
        }
        if (!isEmptyString(str)) {
            if ("null".equals(str)) {
                str = str.replace("null", "");
                return str;
            } else {
                return str;
            }
        } else {
            return str;
        }
    }

    /**
     * 转移SQL的保留字符，比如讲单引号转义为''
     *
     * @param str 需要转义的字符
     * @return 已经转义的字符
     */
    public static String escapeSQLChar(final String str) {
        if (!StringUtils.isEmpty(str)) {
            return str.replaceAll("'", "''");
        }
        return null;
    }

    /**
     * 验证是否是有效的手机号
     *
     * @param mobile 手机号
     * @return
     */
    public final static boolean validMobileNumber(final String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return false;
        }

        Pattern pattern = Pattern.compile(MOBILE_REG);

        if (!pattern.matcher(mobile).matches()) {
            return false;
        }
        return true;
    }

    /**
     * 校验是否是有效的邮件地址
     *
     * @param email 邮箱地址
     * @return 有效则返回真，否则返回假
     */
    public static boolean validEmail(final String email) {
        if (StringUtils.isEmpty(email)) {
            return false;
        }
        Pattern pattern = Pattern.compile(EMAIL_REG);
        if (!pattern.matcher(email).matches()) {
            return false;
        }
        return true;

    }

    /**
     * 校验有效的名称
     *
     * @param nickName 昵称
     * @return 返回真
     */
    public static boolean validUserName(final String userName) {
        /**
         * @ TODO 配置敏感词
         */
        boolean isAllDigit = userName.matches("[0-9]+");
        if (isAllDigit) {
            // 用户名不能为纯数字
            return false;
        }
        return true;
    }

    // /**
    // * 校验有效的昵称
    // * @param nickName 昵称
    // * @return 返回真
    // * 此方法false 表示存在敏感字； true表示没有
    // */
    // public static boolean validNickname(final String nickName) {
    // if(getSensitiveWordService().checkSensitiveWords(nickName,
    // Constant.SENSITIVE_WORD_TYPE.USERNAME.name())){
    // return false;
    // }
    // return true;
    // }

    /**
     * 校验有效的会员卡号
     *
     * @param membershipCard
     * @return
     */
    public final static boolean validMembershipCard(final String membershipCard) {
        // 目前无规则
        return true;
    }

    /**
     * 去除字符串首尾出现的某个字符.
     *
     * @param source  源字符串.
     * @param element 需要去除的字符.
     * @return String.
     */
    public static String trimFirstAndLastChar(String source, char element) {
        boolean beginIndexFlag = true;
        boolean endIndexFlag = true;
        do {
            int beginIndex = source.indexOf(element) == 0 ? 1 : 0;
            int endIndex = source.lastIndexOf(element) + 1 == source.length() ? source.lastIndexOf(element)
                    : source.length();
            source = source.substring(beginIndex, endIndex);
            beginIndexFlag = (source.indexOf(element) == 0);
            endIndexFlag = (source.lastIndexOf(element) + 1 == source.length());
        } while (beginIndexFlag || endIndexFlag);
        return source;
    }

    /**
     * Splits a String on a delimiter into a List of Strings.
     *
     * @param str   the String to split
     * @param delim the delimiter character(s) to join on (null will split on
     *              whitespace)
     * @return a list of Strings
     */
    public static List<String> splitToList(String str, String delim) {
        List<String> splitList = null;
        StringTokenizer st = null;

        if (str == null) {
            return splitList;
        }

        if (delim != null) {
            st = new StringTokenizer(str, delim);
        } else {
            st = new StringTokenizer(str);
        }

        if (st != null && st.hasMoreTokens()) {
            splitList = new ArrayList<String>();

            while (st.hasMoreTokens()) {
                splitList.add(st.nextToken());
            }
        }
        return splitList;
    }

    /**
     * 转换成UTF-8编码
     *
     * @param str
     * @return
     */
    public static String toUTF8(String str) {
        if (StringUtils.isNotEmpty(str)) {
            try {
                return new String(str.getBytes("iso8859-1"), "UTF-8");
            } catch (Exception ex) {
                return "";
            }
        }
        return "";
    }

    /**
     * 屏蔽手机的方法
     *
     * @param source 手机号
     * @return
     */

    public static String hiddenMobile(String source) {
        if (StringUtils.isBlank(source)) {
            return "";
        }

        if (mobilePattern.matcher(source).matches()) {
            return source.substring(0, 3) + "****" + source.substring(7, 11);
        } else {
            return source;
        }

    }

    /**
     * 屏蔽邮箱的方法
     *
     * @param source 邮箱
     * @return
     */
    public static String hiddenEmail(String source) {
        if (StringUtils.isBlank(source)) {
            return "";
        }
        Pattern pattern = Pattern.compile(EMAIL_REG);
        if (pattern.matcher(source).matches()) {
            int splitIndex = source.indexOf("@");
            String emailPrefix = source.substring(0, splitIndex);
            if (emailPrefix.length() > 4) {
                source = source.substring(0, emailPrefix.length() - 4) + "****" + source.substring(splitIndex);
            } else {
                source = source.substring(0, 1) + "****" + source.substring(splitIndex);
            }
            return source;
        } else {
            return source;
        }
    }

    /**
     * 屏蔽身份证号的方法
     *
     * @param source 身份证号
     * @return
     */
    public static String hiddenIDCard(String source) {
        if (StringUtils.isBlank(source)) {
            return "";
        }
        if (source.length() > 8) {
            source = source.substring(0, source.length() - 8) + "********";
        } else {
            source = source.substring(0, 1) + "********";
        }

        return source;

    }

    /**
     * 反射输出实体类所有公共无入参的get和is方法名称和值
     *
     * @param object 实体类对象
     * @return object属性名称名称及属性值
     * @author ZHANG Nan
     */
    public static String printParam(Object object) {
        if (object == null) {
            return "";
        }
        StringBuffer out = new StringBuffer();
        try {
            Class<?> clazz = object.getClass();
            out.append(clazz.getSimpleName());
            out.append(" [");
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                if (method.getName().indexOf("get") >= 0) {
                    Type[] types = method.getGenericParameterTypes();
                    if (types == null || types.length == 0) {
                        Method mtd = clazz.getMethod(method.getName(), new Class[]{});
                        Object value = mtd.invoke(object);
                        if (value != null) {
                            out.append(method.getName() + "=" + value.toString() + ",");
                        }
                    }
                }
            }
            out.append("]");
        } catch (Exception e) {
        }
        return out.toString();
    }

    /**
     * 用变量值替换字符串模板中的变量
     *
     * @param template 模板
     * @param varStart 变量开始字符串
     * @param varEnd   变量结束字符串
     * @param values   变量值
     * @return
     */
    public static String buildStringByTemplate(String template, String varStart, String varEnd,
                                               Map<String, String> values) {
        String s = template;
        for (String key : values.keySet()) {
            s = s.replace(varStart + key + varEnd, values.get(key) == null ? "" : values.get(key));
        }
        return s;
    }

    /**
     * 把字节数组保存为一个文件
     *
     * @Author Sean.guo
     * @EditTime 2007-8-13 上午11:45:56
     */
    public static File getFileFromBytes(byte[] b, String outputFile) throws Exception {
        BufferedOutputStream stream = null;
        FileOutputStream fstream = null;
        File file = null;
        try {
            file = new File(outputFile);
            fstream = new FileOutputStream(file);
            stream = new BufferedOutputStream(fstream);
            stream.write(b);
        } catch (Exception e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(stream);
            IOUtils.closeQuietly(fstream);
        }
        return file;
    }

    /**
     * 替换或截短用户名 若用户名是手机号、邮箱或用户名为lv+手机号，则部分字符用*替换，其它根据传入的长度截短
     *
     * @param len      (-1表示不截短)
     * @param userName
     * @return
     */
    public static String replaceOrCutUserName(int len, String userName) {

        String str = realplayMobleAndEmail(userName);

        if (!str.equals(userName)) {
            return str;
        } else if (userNamePt.matcher(userName).find() && validMobileNumber(userName.substring(2, userName.length()))) {
            return userName.substring(0, userName.length() - 4) + "****";
        }

        return len == -1 ? str : cutString2(len, str);
    }

    public static String hidenUserName(String userName) {
        if (StringUtils.isBlank(userName)) {
            return userName;
        }
        return userName.substring(0, 1) + "**";
    }

    public static String realplayMobleAndEmail(final String str) {
        try {
            String s = str;
            // 手机
            Pattern p = Pattern.compile(MOBILE_REG);
            // 邮件
            Pattern p2 = Pattern.compile(EMAIL_REG);
            Matcher m2 = p2.matcher(str);
            Matcher m = p.matcher(str);
            if (s.length() == 11 && m.find()) {
                String st = s.substring(0, 7);
                s = st + "****";
            } else if (m2.find()) {
                int i = s.indexOf("@");
                String st = s.substring(0, i + 1);
                s = st + "****";
            }
            return s;
        } catch (Exception e) {
            return str;
        }
    }

    public static String cutString2(int len, String source) {
        if (source.length() >= len) {
            return source.substring(0, len) + "… ";
        } else {
            return source;
        }
    }

    public static String cutString(int len, String source) {
        if (source.length() >= len) {
            return source.substring(0, len) + "… ";
        } else {
            return source;
        }
    }

    /**
     * 处理 "null"
     *
     * @param value
     * @return
     */
    public static String coverNullStrValue(String value) {
        if ("null".equals(value) || value == null) {
            return "";
        }
        return value;
    }

    /**
     * 替换null对象或者null字符
     *
     * @param object
     * @return
     * @author dengcheng
     */
    public static String trimNullValue(String object) {
        if (object == null || "null".equals(object)) {
            return "";
        }
        return object;
    }

    /**
     * 变换数组为字符串
     *
     * @param arr
     * @return
     */
    public static String arrToStr(String[] arr) {
        String str = null;
        if (arr != null) {
            str = org.springframework.util.StringUtils
                    .quote(org.springframework.util.StringUtils.arrayToDelimitedString(arr, "','"));
        }
        return str;
    }

    /**
     * 过滤html文档
     *
     * @param inputString
     * @return
     */
    public static String filterOutHTMLTags(String inputString) {
        String htmlStr = inputString; // 含html标签的字符串
        String textStr = "";
        Pattern p_script;
        Matcher m_script;
        Pattern p_style;
        Matcher m_style;
        Pattern p_html;
        Matcher m_html;

        try {
            String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>"; // 定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script>
            // //
            // }
            String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>"; // 定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
            String regEx_html = "<[^>]+>"; // 定义HTML标签的正则表达式

            p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);
            m_script = p_script.matcher(htmlStr);
            htmlStr = m_script.replaceAll(""); // 过滤script标签

            p_style = Pattern.compile(regEx_style, Pattern.CASE_INSENSITIVE);
            m_style = p_style.matcher(htmlStr);
            htmlStr = m_style.replaceAll(""); // 过滤style标签

            p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
            m_html = p_html.matcher(htmlStr);
            htmlStr = m_html.replaceAll(""); // 过滤html标签

            textStr = htmlStr;
        } catch (Exception e) {
            System.err.println("Html2Text: " + e.getMessage());
        }
        return textStr;// 返回文本字符串
    }

    public static boolean isIdCard(String idNumber) {
        if (idNumber.length() == 18) {
            String pattern = "((11|12|13|14|15|21|22|23|31|32|33|34|35|36|37|41|42|43|44|45|46|50|51|52|53|54|61|62|63|64|65|71|81|82|91)\\d{4})((((19|20)(([02468][048])|([13579][26]))0229))|((20[0-9][0-9])|(19[0-9][0-9]))((((0[1-9])|(1[0-2]))((0[1-9])|(1\\d)|(2[0-8])))|((((0[1,3-9])|(1[0-2]))(29|30))|(((0[13578])|(1[02]))31))))((\\d{3}(x|X))|(\\d{4}))";
            Pattern p = Pattern.compile(pattern);
            Matcher m = p.matcher(idNumber);
            return m.matches();
        } else {
            String pattern = "((11|12|13|14|15|21|22|23|31|32|33|34|35|36|37|41|42|43|44|45|46|50|51|52|53|54|61|62|63|64|65|71|81|82|91)\\d{4})((((([02468][048])|([13579][26]))0229))|([0-9][0-9])((((0[1-9])|(1[0-2]))((0[1-9])|(1\\d)|(2[0-8])))|((((0[1,3-9])|(1[0-2]))(29|30))|(((0[13578])|(1[02]))31))))(\\d{3})";
            Pattern p = Pattern.compile(pattern);
            Matcher m = p.matcher(idNumber);
            return m.matches();
        }

    }

    public static boolean isPinyin(String keyword) {
        Matcher m = pinyinPattern.matcher(keyword);
        return m.matches();
    }

    /**
     * 判断是否是数字(>=0 不包括负数)
     *
     * @param str
     * @return
     * @author:nixianjun 2013-6-24
     */
    public static boolean isNumber(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        return str.matches("^\\d+");
    }

    /**
     * 将文本内容替换成可以在js中正常显示的内容，如将双引转意
     *
     * @param str
     * @return
     */
    public static String outputJSContent(String str) {
        if (StringUtils.isNotEmpty(str)) {
            return str.replaceAll("\"", "\\\\\"");
        } else {
            return "";
        }
    }

    /**
     * 过滤我们产品中的参数，返回正确字符串给coremetrics
     *
     * @param str
     * @return
     */
    public static String outputCoremetricsParam(String str) {
        if (StringUtils.isNotEmpty(str)) {
            str = str.replaceAll("\\(", "");
            str = str.replaceAll("\\)", "");
            return str;
        } else {
            return "";
        }
    }

    /**
     * 判断两个字符串的内容是否相同
     *
     * @param s1
     * @param s2
     */
    public static boolean isSame(String s1, String s2) {
        if (s1 != null) {
            return s1.equals(s2);
        } else if (s2 != null) {
            return s2.equals(s1);
        } else {
            return true;
        }
    }

    /**
     * 判断字符串是否为数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String content) {
        try {
            Double.parseDouble(content);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }

    }

    /**
     * 功能：判断字符串是否为日期格式
     *
     * @param str
     * @return
     */
    public static boolean isDate(String strDate) {
        if (StringUtils.isBlank(strDate)) {
            return false;
        }

        Matcher m = datePattern.matcher(strDate);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }

    public static String getContent(Map<String, String> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);// 对参数排序，已确保拼接的签名顺序正确
        String prestr = "";
        boolean first = true;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (value == null || value.trim().length() == 0) {
                continue;
            }
            if (first) {
                prestr = prestr + key + "=" + value;
                first = false;
            } else {
                prestr = prestr + "&" + key + "=" + value;
            }
        }
        return prestr;
    }

    /**
     * 转换map为get请求参数<br/>
     * 分隔符为&
     *
     * @param map
     * @return
     */
    public static String convertMapToString(Map<String, String> map) {
        StringBuffer prestr = new StringBuffer();
        for (Entry<String, String> entry : map.entrySet()) {
            prestr.append("&" + entry.getKey() + "=" + (entry.getValue() == null ? "" : entry.getValue()));
        }
        if (prestr.length() > 0) {
            return prestr.toString().substring(1);
        }
        return prestr.toString();
    }

    /**
     * "file:/home/whf/cn/fh" -> "/home/whf/cn/fh"
     * "jar:file:/home/whf/foo.jar!cn/fh" -> "/home/whf/foo.jar"
     */
    public static String getRootPath(URL url) {
        String fileUrl = url.getFile();
        int pos = fileUrl.indexOf('!');

        if (-1 == pos) {
            return fileUrl;
        }

        return fileUrl.substring(5, pos);
    }

    public static String dotToSplash(String name, String... ignoreSuffix) {
        if (null == ignoreSuffix) {
            return name.replaceAll("\\.", "/");
        }

        String suffix0 = null;

        for (String suffix : ignoreSuffix) {
            if (name.endsWith("." + suffix)) {
                suffix0 = suffix;
                break;
            }
        }

        if (null == suffix0) {
            return name.replaceAll("\\.", "/");
        }

        if (!name.endsWith("." + suffix0)) {
            return name.replaceAll("\\.", "/");
        } else {
            name = name.replace("." + suffix0, "##" + suffix0);
            name = name.replaceAll("\\.", "/");
            name = name.replaceAll("##" + suffix0, "." + suffix0);
            return name;
        }
    }

    public static String splashToDot(String name, String... ignoreSuffix) {
        if (null == ignoreSuffix) {
            return name.replaceAll("\\/", "\\.");
        }

        String suffix0 = null;

        for (String suffix : ignoreSuffix) {
            if (name.endsWith("." + suffix)) {
                suffix0 = suffix;
                break;
            }
        }

        if (null == suffix0) {
            return name.replaceAll("\\/", "\\.");
        }

        if (!name.endsWith("." + suffix0)) {
            return name.replaceAll("\\/", "\\.");
        } else {
            name = name.replace("." + suffix0, "##" + suffix0);
            name = name.replaceAll("\\/", "\\.");
            name = name.replaceAll("##" + suffix0, "." + suffix0);
            return name;
        }
    }

    /**
     * "Apple.class" -> "Apple"
     */
    public static String trimExtension(String name) {
        // int pos = name.indexOf('.');
        // if (-1 != pos)
        // {
        // return name.substring(0, pos);
        // }
        //
        // return name;

        int pos = name.lastIndexOf(".");
        if (-1 != pos) {
            return name.substring(0, pos);
        }

        return name;

    }

    /**
     * /application/home -> /home
     *
     * @param uri
     * @return
     */
    public static String trimURI(String uri) {
        String trimmed = uri.substring(1);
        int splashIndex = trimmed.indexOf('/');

        return trimmed.substring(splashIndex);
    }

    /**
     * @param src    源字符
     * @param target 需要补充的字符
     * @param length 补充后的长度
     * @return String
     * @description 左补位
     */
    public static String lpud(String src, CharSequence target, int length) {
        if (isEmptyString(src)) {
            return src;
        }
        StringBuilder buf = new StringBuilder(src);
        while (buf.length() < length) {
            buf.insert(0, target);
        }
        return buf.toString();
    }

    /**
     * @param chineseNumber
     * @return int
     * @description 中文转数字
     */
    public static int chineseNumberToInt(String chineseNumber) {
        int result = 0;
        int temp = 1;// 存放一个单位的数字如：十万
        int count = 0;// 判断是否有chArr
        char[] cnArr = new char[]{'一', '二', '三', '四', '五', '六', '七', '八', '九'};
        char[] chArr = new char[]{'十', '百', '千', '万', '亿'};
        for (int i = 0; i < chineseNumber.length(); i++) {
            boolean b = true;// 判断是否是chArr
            char c = chineseNumber.charAt(i);
            for (int j = 0; j < cnArr.length; j++) {// 非单位，即数字
                if (c == cnArr[j]) {
                    if (0 != count) {// 添加下一个单位之前，先把上一个单位值添加到结果中
                        result += temp;
                        temp = 1;
                        count = 0;
                    }
                    // 下标+1，就是对应的值
                    temp = j + 1;
                    b = false;
                    break;
                }
            }
            if (b) {// 单位{'十','百','千','万','亿'}
                for (int j = 0; j < chArr.length; j++) {
                    if (c == chArr[j]) {
                        switch (j) {
                            case 0:
                                temp *= 10;
                                break;
                            case 1:
                                temp *= 100;
                                break;
                            case 2:
                                temp *= 1000;
                                break;
                            case 3:
                                temp *= 10000;
                                break;
                            case 4:
                                temp *= 100000000;
                                break;
                            default:
                                break;
                        }
                        count++;
                    }
                }
            }
            if (i == chineseNumber.length() - 1) {// 遍历到最后一个字符
                result += temp;
            }
        }
        return result;
    }

    public static boolean isUuid(String str) {
        boolean result = false;
        try {
            if (isNotEmptyString(str)) {
                UUID.fromString(str);
                result = true;
            }
        } catch (Exception e) {
            result = false;
        }
        return result;
    }

    public static String emptyIf(String value, String defaultValue) {
        if (isInvalid(value)) {
            return defaultValue;
        }
        return value;
    }

    /**
     * 转换表名到类名 如admin_t转成AdminT
     *
     * @param sqlName
     * @return
     */
    public static String makeAllWordFirstLetterUpperCase(String sqlName) {
        String[] strs = sqlName.toLowerCase().split("_");
        String result = "";
        String preStr = "";
        for (int i = 0; i < strs.length; i++) {
            if (preStr.length() == 1) {
                result += strs[i];
            } else {
                result += capitalize(strs[i]);
            }
            preStr = strs[i];
        }
        return result;
    }

    /**
     * 如果参数1有效就返回参数1,否则返回参数2
     *
     * @param str0
     * @param str1
     * @return
     */
    public static String getString(String str0, String str1) {
        return isInvalid(str0) ? str1 : str0;
    }

    /**
     * 根据参数，将首字母转成大写或者小写 如将LoginLog变成loginLog或将 loginLog变成LoginLog
     *
     * @param changType
     * @return
     */
    public static String changFirstWord(String str, int changType) {
        if (isInvalid(str)) {
            return "";
        }
        String first = str.substring(0, 1);
        String second = str.substring(1);

        switch (changType) {
            // 小写
            case toLowerCase:
                first = first.toLowerCase();
                break;

            // 大写
            case toUpperCase:
                first = first.toUpperCase();
                break;
            default:
                break;
        }

        String result = first + second;
        return result;
    }

    /**
     * 判断是否为空
     */
    public static boolean isInvalid(String value) {
        return (value == null || value.trim().length() == 0);
    }

    public static String replace(String inString, String oldPattern, String newPattern) {
        if (inString == null) {
            return null;
        }
        if (oldPattern == null || newPattern == null) {
            return inString;
        }

        StringBuffer sbuf = new StringBuffer();
        // output StringBuffer we'll build up
        int pos = 0; // our position in the old string
        int index = inString.indexOf(oldPattern);
        // the index of an occurrence we've found, or -1
        int patLen = oldPattern.length();
        while (index >= 0) {
            sbuf.append(inString.substring(pos, index));
            sbuf.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sbuf.append(inString.substring(pos));

        // remember to append any characters to the right of a match
        return sbuf.toString();
    }

    /**
     * ����ĸ��copy from spring
     */
    public static String capitalize(String str) {
        return changeFirstCharacterCase(str, true);
    }

    /**
     * ����ĸСдcopy from spring
     */
    public static String uncapitalize(String str) {
        return changeFirstCharacterCase(str, false);
    }

    /**
     * copy from spring
     */
    private static String changeFirstCharacterCase(String str, boolean capitalize) {
        if (str == null || str.length() == 0) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str.length());
        if (capitalize) {
            buf.append(Character.toUpperCase(str.charAt(0)));
        } else {
            buf.append(Character.toLowerCase(str.charAt(0)));
        }
        buf.append(str.substring(1));
        return buf.toString();
    }

    private static final Random RANDOM = new Random();

    public static String randomNumeric(int count) {
        return random(count, false, true);
    }

    public static String random(int count, boolean letters, boolean numbers) {
        return random(count, 0, 0, letters, numbers);
    }

    public static String random(int count, int start, int end, boolean letters, boolean numbers) {
        return random(count, start, end, letters, numbers, null, RANDOM);
    }

    public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars,
                                Random random) {
        if (count == 0) {
            return "";
        } else if (count < 0) {
            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
        }
        if ((start == 0) && (end == 0)) {
            end = 'z' + 1;
            start = ' ';
            if (!letters && !numbers) {
                start = 0;
                end = Integer.MAX_VALUE;
            }
        }

        char[] buffer = new char[count];
        int gap = end - start;

        while (count-- != 0) {
            char ch;
            if (chars == null) {
                ch = (char) (random.nextInt(gap) + start);
            } else {
                ch = chars[random.nextInt(gap) + start];
            }
            if ((letters && Character.isLetter(ch)) || (numbers && Character.isDigit(ch)) || (!letters && !numbers)) {
                if (ch >= 56320 && ch <= 57343) {
                    if (count == 0) {
                        count++;
                    } else {
                        // low surrogate, insert high surrogate after putting it
                        // in
                        buffer[count] = ch;
                        count--;
                        buffer[count] = (char) (55296 + random.nextInt(128));
                    }
                } else if (ch >= 55296 && ch <= 56191) {
                    if (count == 0) {
                        count++;
                    } else {
                        // high surrogate, insert low surrogate before putting
                        // it in
                        buffer[count] = (char) (56320 + random.nextInt(128));
                        count--;
                        buffer[count] = ch;
                    }
                } else if (ch >= 56192 && ch <= 56319) {
                    // private high surrogate, no effing clue, so skip it
                    count++;
                } else {
                    buffer[count] = ch;
                }
            } else {
                count++;
            }
        }
        return new String(buffer);
    }

    /**
     * Convert a name in camelCase to an underscored name in lower case. Any upper
     * case letters are converted to lower case with a preceding underscore.
     *
     * @param filteredName the string containing original name
     * @return the converted name
     */
    public static String toUnderscoreName(String name) {
        if (name == null) {
            return null;
        }

        String filteredName = name;
        if (filteredName.indexOf("_") >= 0 && filteredName.equals(filteredName.toUpperCase())) {
            filteredName = filteredName.toLowerCase();
        }
        if (filteredName.indexOf("_") == -1 && filteredName.equals(filteredName.toUpperCase())) {
            filteredName = filteredName.toLowerCase();
        }

        StringBuffer result = new StringBuffer();
        if (filteredName != null && filteredName.length() > 0) {
            result.append(filteredName.substring(0, 1).toLowerCase());
            for (int i = 1; i < filteredName.length(); i++) {
                String preChart = filteredName.substring(i - 1, i);
                String c = filteredName.substring(i, i + 1);
                if (c.equals("_")) {
                    result.append("_");
                    continue;
                }
                if (preChart.equals("_")) {
                    result.append(c.toLowerCase());
                    continue;
                }
                if (c.matches("\\d")) {
                    result.append(c);
                } else if (c.equals(c.toUpperCase())) {
                    result.append("_");
                    result.append(c.toLowerCase());
                } else {
                    result.append(c);
                }
            }
        }
        return result.toString();
    }

    /**
     * 用指定字符分割并获取最后一段,如 java.util.regex.Pattern获取到Pattern
     *
     * @param str
     * @param split
     * @return
     */
    public static String getLastSection(String str, String split) {
        String str2 = str.substring(str.lastIndexOf(split) + 1, str.length());
        return str2;
    }


    /**
     * 获取指定分割段,如NotBlank.user.realName,index为1时得到user.realName
     *
     * @param str
     * @param split
     * @return
     */
    public static String getBySplitIndex(String str, String split, int index) {
        int index0 = str.indexOf(split);
        String str2 = str;
        int count = 0;
        while (index0 > 0 && count < index) {
            count++;
            str2 = str.substring(index0 + 1);
            index0 = str2.indexOf(split);
        }
        return str2;
    }

    /**
     * 判断IP地址的合法性，这里采用了正则表达式的方法来判断
     * return true，合法
     */
    public static boolean ipCheck(String text) {
        if (isNotEmpty(text)) {
            // 定义正则表达式
            String regex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." +
                    "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." +
                    "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." +
                    "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$";
            // 判断ip地址是否与正则表达式匹配
            if (text.matches(regex)) {
                // 返回判断信息
                return true;
            } else {
                // 返回判断信息
                return false;
            }
        }
        return false;
    }

    public static String leftPad(final Integer value, final int size, String padStr) {
        return leftPad(String.valueOf(value), size, padStr);
    }

    public static String leftPad(final Long value, final int size, String padStr) {
        return leftPad(String.valueOf(value), size, padStr);
    }

    public static String leftPad(final Byte value, final int size, String padStr) {
        return leftPad(String.valueOf(value), size, padStr);
    }

    public static String leftPad0(final Integer value, final int size) {
        return leftPad(String.valueOf(value), size, "0");
    }

    public static String leftPad0(final Long value, final int size) {
        return leftPad(String.valueOf(value), size, "0");
    }

    public static String leftPad0(final Byte value, final int size) {
        return leftPad(String.valueOf(value), size, "0");
    }


    /**
     * 将字符串转成对应的类型值
     *
     * @param str
     * @param clazz
     * @return
     */
    public static Object parseStr(String str, Class<?> clazz) {
        Object obj = str;
        if (Integer.class.equals(clazz)) {
            obj = Integer.valueOf(str);
        } else if (Byte.class.equals(clazz)) {
            obj = Byte.valueOf(str);
        } else if (Long.class.equals(clazz)) {
            obj = Long.valueOf(str);
        } else if (Double.class.equals(clazz)) {
            obj = Double.valueOf(str);
        } else if (Float.class.equals(clazz)) {
            obj = Float.valueOf(str);
        } else if (Short.class.equals(clazz)) {
            obj = Short.valueOf(str);
        } else if (Boolean.class.equals(clazz)) {
            obj = Boolean.valueOf(str);
        }
        return obj;
    }

    private static Pattern linePattern = Pattern.compile("_(\\w)");
    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    /**
     * 驼峰转下划线
     *
     * @param str
     * @return
     */
    public static String humpToLine(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 下划线转驼峰,正常输出
     *
     * @param str
     * @return
     */
    public static String lineToHump(String str) {
        Matcher matcher = linePattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static String joinInt(List<Integer> list, String sepa) {
        String result = "";
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                result += list.get(i);
                if (i < list.size() - 1) {
                    result += sepa;
                }
            }
        }
        return result;
    }

//    public static String joinWithQuotation(List<Integer> list, String sepa) {
////        String result = "";
//        StringBuffer stringBuffer = new StringBuffer("");
//        if (list != null) {
//            for (int i = 0; i < list.size(); i++) {
//                stringBuffer.append("'").append(list.get(i)).append("'");
////                result += "'" + list.get(i) + "'";
//                if (i < list.size() - 1) {
////                    result += sepa;
//                    stringBuffer.append(sepa);
//                }
//            }
//        }
//        return stringBuffer.toString();
//    }

//    public static String join(List<Integer> list, String sepa) {
//        StringBuffer stringBuffer = new StringBuffer("");
//        if (list != null) {
//            for (int i = 0; i < list.size(); i++) {
//                stringBuffer.append(list.get(i));
//                if (i < list.size() - 1) {
//                    stringBuffer.append(sepa);
//                }
//            }
//        }
//        return stringBuffer.toString();
//    }

    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").toLowerCase();
    }

    /**
     * 格式化文本, {} 表示占位符<br>
     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
     * 如果想输出 {} 使用 \\转义 { 即可，如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
     * 例：<br>
     * 通常使用：format("this is {} for {}", "a", "b") -> this is a for b<br>
     * 转义{}： format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * 转义\： format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param template 文本模板，被替换的部分用 {} 表示
     * @param params   参数值
     * @return 格式化后的文本
     */
    public static String format(String template, Object... params) {
        if (CheckUtil.isEmpty(params) || isEmpty(template)) {
            return template;
        }
        return StrFormatter.format(template, params);
    }

}
